package com.anjie.powerproject.controller;


import com.anjie.powerproject.common.Result;
import com.anjie.powerproject.entity.*;
import com.anjie.powerproject.pojo.CustomAtlasDevice;
import com.anjie.powerproject.pojo.dto.CompareDTO;
import com.anjie.powerproject.pojo.dto.DeviceDTO;
import com.anjie.powerproject.pojo.dto.DeviceInfoDTO;
import com.anjie.powerproject.repository.DeviceTypeRepository;
import com.anjie.powerproject.service.DeviceService;
import com.anjie.powerproject.service.GraphInfoService;
import com.anjie.powerproject.service.PointService;
import com.anjie.powerproject.service.RelationshipService;
import com.anjie.powerproject.service.impl.GraphDevServiceImpl;
//import com.anjie.powerproject.util.FtpUtil;
import com.anjie.powerproject.util.ReadXml;
import org.apache.commons.io.FileUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("device")
public class DeviceController {

    public static final String UPLOAD_IMG = "image_upload";
//    public static final String PIC_HOST = "192.168.40.27";
//    public static final String PIC_HOST = "localhost";
//    public static final String PORT = "10086";

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceTypeRepository deviceTypeRepository;

    @Autowired
    private RelationshipService relationshipService;

    @Autowired
    private GraphInfoService graphInfoService;

    @Autowired
    private GraphDevServiceImpl graphDevService;

    @Autowired
    private PointService pointService;

    /**
     * 根据设备的id删除设备，返回设备列表页面
     * @param deviceId
     * @return
     */
    @GetMapping("/delete/{device_id}")
    @ResponseBody
    private Map deleteDevice(@PathVariable(value = "device_id") Integer deviceId){
        //若在其他图谱中使用则提示不允许删除
        boolean flag = graphDevService.findGraphDevsByDeviceId(deviceId);
        Map msg = new HashMap();
        if(flag){
            msg.put("status",0);
        }else {
            deviceService.deleteDeviceById(deviceId);
            msg.put("status",1);
        }
        return msg;
    }

    /**
     * 获取所有设备列表json格式,拖拽页面使用
     * @param graphId
     * @return
     */
    @GetMapping("/getGraphDeviceList/{graphId}")
    @ResponseBody
    private Map getGraphDeviceList(@PathVariable(value = "graphId") Integer graphId){
        List<Device> devices = deviceService.getAllDevices();
        Map map = new HashMap();
        map.put("graphDeviceList",devices);
        return map;
    }

    /**
     * 获取所有设备列表，返回页面
     * @param model
     * @return
     */
    @GetMapping("/getAll")
    private String getAllDevice(Model model){

        List<Device> deviceList = deviceService.getAllDevices();
        List<DeviceInfoDTO> deviceInfoDTOS=new ArrayList<>();
        List<Point> pointList=pointService.getPointList();
        Map<Integer, Point> pointMap = pointList.stream().collect(Collectors.toMap(Point::getId, object -> object));

        for (Device device:deviceList) {
            DeviceInfoDTO deviceInfoDTO=new DeviceInfoDTO();
            BeanUtils.copyProperties(device,deviceInfoDTO);
            if(device.getDevPointId()!=null) {
//                Point devPoint = pointService.getPointById(device.getDevPointId());
                Point devPoint=pointMap.get(device.getDevPointId());
//                deviceInfoDTO.setDevName(devPoint != null ? devPoint.getPointName() : "点位不存在");
                deviceInfoDTO.setDevName(devPoint.getPointName());
            }
//            else deviceInfoDTO.setDevName("无对应点位");
            if(device.getBatteryPointId()!=null) {
//                Point BatteryPoint = pointService.getPointById(device.getBatteryPointId());
                Point BatteryPoint = pointMap.get(device.getBatteryPointId());
//                deviceInfoDTO.setBatteryName(BatteryPoint != null ? BatteryPoint.getPointName() : "点位不存在");
                deviceInfoDTO.setBatteryName(BatteryPoint.getPointName());
            }
//            else deviceInfoDTO.setBatteryName("无对应点位");
            if(device.getTemperaturePointId()!=null) {
//                Point TemperaturePoint = pointService.getPointById(device.getTemperaturePointId());
                Point TemperaturePoint = pointMap.get(device.getTemperaturePointId());
//                deviceInfoDTO.setTemperatureName(TemperaturePoint != null ? TemperaturePoint.getPointName() : "点位不存在");
                deviceInfoDTO.setTemperatureName(TemperaturePoint.getPointName());
            }
//            else deviceInfoDTO.setTemperatureName("无对应点位");

            deviceInfoDTOS.add(deviceInfoDTO);
        }
//        System.out.println(deviceList.toString());
        model.addAttribute("deviceInfoDTOS",deviceInfoDTOS);
//        System.out.println(deviceInfoDTOS.toString());
        return "device";
    }

    /**
     * 根据设备id获取设备，并跳转到设备修改页面
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/get/{id}")
    private String getDevice(@PathVariable("id") Integer id,Model model){
        Device device = deviceService.findDeviceById(id);
        DeviceInfoDTO deviceInfoDTO=new DeviceInfoDTO();
        BeanUtils.copyProperties(device,deviceInfoDTO);

        if(device.getDevPointId()!=null) {
            Point devPoint = pointService.getPointById(device.getDevPointId());
            deviceInfoDTO.setDevName(devPoint != null ? devPoint.getPointName() : "点位不存在");
        }else deviceInfoDTO.setDevName("无对应点位");
        if(device.getBatteryPointId()!=null) {
            Point BatteryPoint = pointService.getPointById(device.getBatteryPointId());
            deviceInfoDTO.setBatteryName(BatteryPoint != null ? BatteryPoint.getPointName() : "点位不存在");
        }else deviceInfoDTO.setBatteryName("无对应点位");
        if(device.getTemperaturePointId()!=null) {
            Point TemperaturePoint = pointService.getPointById(device.getTemperaturePointId());
            deviceInfoDTO.setTemperatureName(TemperaturePoint != null ? TemperaturePoint.getPointName() : "点位不存在");
        }else deviceInfoDTO.setTemperatureName("无对应点位");

        if(device.getDeviceType().getTypeId()==2){ //如果是储能设备
            if(device.getEndFlagId()!=null) {
                Point endFlagPoint = pointService.getPointById(device.getEndFlagId());
                deviceInfoDTO.setEndFlagName(endFlagPoint != null ? endFlagPoint.getPointName() : "点位不存在");
            }else deviceInfoDTO.setEndFlagName("无对应点位");
        }

        String workTime = device.getWorkTime();
        String[] split = workTime.split("-");
        model.addAttribute("startTime",split[0]);
        model.addAttribute("endTime",split[1]);
        model.addAttribute("device",deviceInfoDTO);
        return "deviceEdit";
    }

    /**
     * 根据关系边的源设备id获取包括该设备的所有边，返回json格式的数据,接口未用到
     * @param device_from
     * @return
     */
    /*@GetMapping("/getDeviceName/{device_from}")
    @ResponseBody
    private Map getDeviceName(@PathVariable(value = "device_from")Integer device_from){
        Map map = new HashMap();
        List relationship = relationshipService.findCustomRelationship(device_from);
        map.put("relationship",relationship);
        return map;
    }*/

    /**
     * 根据id获取设备的信息，并跳转到查看界面
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/getDeviceInfo/{id}")
    private String getDeviceInfo(@PathVariable("id") Integer id,Model model){
        Device device = deviceService.findDeviceById(id);
        DeviceInfoDTO deviceInfoDTO=new DeviceInfoDTO();
        BeanUtils.copyProperties(device,deviceInfoDTO);
        if(device.getDevPointId()!=null) {
            Point devPoint = pointService.getPointById(device.getDevPointId());
            deviceInfoDTO.setDevName(devPoint != null ? devPoint.getPointName() : "点位不存在");
        }else deviceInfoDTO.setDevName("点位不存在");
        if(device.getBatteryPointId()!=null) {
            Point BatteryPoint = pointService.getPointById(device.getBatteryPointId() != null ? device.getBatteryPointId() : 3);
            deviceInfoDTO.setBatteryName(BatteryPoint != null ? BatteryPoint.getPointName() : "点位不存在");
        }else deviceInfoDTO.setBatteryName("点位不存在");
        if(device.getTemperaturePointId()!=null) {
            Point TemperaturePoint = pointService.getPointById(device.getTemperaturePointId() != null ? device.getTemperaturePointId() : 3);
            deviceInfoDTO.setTemperatureName(TemperaturePoint != null ? TemperaturePoint.getPointName() : "点位不存在");
        }else deviceInfoDTO.setTemperatureName("点位不存在");

        if(device.getDeviceType().getTypeId()==2){ //如果是储能设备
            if(device.getEndFlagId()!=null) {
                Point endFlagPoint = pointService.getPointById(device.getEndFlagId());
                deviceInfoDTO.setEndFlagName(endFlagPoint != null ? endFlagPoint.getPointName() : "点位不存在");
            }else deviceInfoDTO.setEndFlagName("无对应点位");
        }

        String workTime = device.getWorkTime();
        String[] split = workTime.split("-");
        model.addAttribute("startTime",split[0]);
        model.addAttribute("endTime",split[1]);
        model.addAttribute("device",deviceInfoDTO);
        return "deviceInfo";
    }

    /**
     * 跳转添加界面
     * @param typeId
     * @param model
     * @return
     */
    @GetMapping("/add/{type_id}")
    public String toAddPage(@PathVariable("type_id") Integer typeId,Model model){
        DeviceType deviceType = deviceTypeRepository.findById(typeId).orElse(null);
        model.addAttribute("deviceType",deviceType);
        return "deviceAdd";
    }

    /**
     * 设备添加处理，保存设备的图片信息和设备普通信息，然后将设备重定向到设备列表界面
     * @param type_id
     * @param request
     * @param device
     * @param pic
     * @return
     * @throws IOException
     */
    @PostMapping("/addDevice")
    @ResponseBody
    public Result<Integer> addDevice(Integer type_id, HttpServletRequest request, Device device, @RequestParam("pic")MultipartFile[] pic) throws IOException {
        //String base = request.getServletContext().getRealPath("WEB-INF/classes/static/images/");
        String base = ResourceUtils.getURL("classpath:").getPath() + "static/images/";
        float cap=device.getCap();  // 能量上限
        float power=device.getPower();  // 均每⼩时产能量
        if(power>cap)
            return Result.error("平均每小时产能量不应大于能量上线");//错误页面

        if (pic!=null||pic.length>0){
            for (int i = 0 ;i<pic.length;i++){
                if (!"".equals(pic[i].getOriginalFilename())) {
                    String fileName = UUID.randomUUID().toString() + pic[i].getOriginalFilename().substring(pic[i].getOriginalFilename().lastIndexOf("."));
                    //pic[i].transferTo(new File(base + fileName));
                    File imgFile = new File(base + fileName);
                    FileUtils.copyInputStreamToFile(pic[i].getInputStream(), imgFile);
                    if (i == 0) {
                        device.setPicPath("/multipower/images/" + fileName);
                    } else {
                        device.setHighlightPicPath("/multipower/images/" + fileName);
                    }
                }
            }
        }

        DeviceType deviceType = deviceTypeRepository.findById(type_id).orElse(null);
        String[] propertyName = request.getParameterValues("propertyName");
        String[] propertyValue = request.getParameterValues("propertyValue");
        String[] times = request.getParameterValues("time");

        //String[] intervalTime = request.getParameterValues("intervalTime");
        List<AdditionalProperties> propertyList = new ArrayList<>();
        if (propertyName!=null&&propertyValue!=null) {
            for (int i = 0; i < propertyName.length; i++) {
                AdditionalProperties property = new AdditionalProperties(propertyName[i], propertyValue[i]);
                property.setDevice(device);
                propertyList.add(property);
            }
        }

        //根据pointId找到对应的devCode 前端只传pointId，devCode需要后端从数据库中查
        if(device.getDevPointId()!=null) {
            Point devPoint = pointService.getPointById(device.getDevPointId());
            device.setDevCode(devPoint != null ? devPoint.getDevCode() : "点位不存在");
        }
//        else device.setDevCode("无对应点位");
        if(device.getBatteryPointId()!=null) {
            Point BatteryPoint = pointService.getPointById(device.getBatteryPointId());
            device.setBatteryCode(BatteryPoint != null ? BatteryPoint.getDevCode() : "点位不存在");
        }
//        else device.setBatteryCode("无对应点位");
        if(device.getTemperaturePointId()!=null) {
            Point TemperaturePoint = pointService.getPointById(device.getTemperaturePointId());
            device.setTemperatureCode(TemperaturePoint != null ? TemperaturePoint.getDevCode() : "点位不存在");
        }
//        else device.setTemperatureCode("无对应点位");

        device.setPropertyList(propertyList);
        device.setDeviceType(deviceType);
        device.setCreate_time(new Date());
        device.setWorkTime(times[0]+"-"+times[1]);
        //device.setIntervalTime(intervalTime[0]);
//        System.out.println(device.toString());

        //device.setPowerMonitorSwitch(powerMonitorSwitch);
        Device savedDevice = deviceService.saveAndFlush(device);
//        return "redirect:/device/"+device.getDeviceType().getTypeId();
        return Result.ok(device.getDeviceType().getTypeId());
    }

    /**
     * 修改设备的信息，页面的跳转交由前端去处理
     * @param device
     * @param pic
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/update")
    @ResponseBody
    private Map updateDevice(Device device, @RequestParam("pic") MultipartFile[] pic,HttpServletRequest request) throws IOException {
        String base = request.getServletContext().getRealPath("WEB-INF/classes/static/images/");

//        System.out.println("-----"+device.toString());

        Map map = new HashMap();
        String[] propertyId = request.getParameterValues("propertyId");
        String[] propertyName = request.getParameterValues("propertyName");
        String[] propertyValue = request.getParameterValues("propertyValue");
        String[] times = request.getParameterValues("time");

        //String[] intervalTime = request.getParameterValues("intervalTime");

        Device deviceById = deviceService.findDeviceById(device.getDeviceId());
        deviceById.setDeviceName(device.getDeviceName()!=null?device.getDeviceName():deviceById.getDeviceName());
        deviceById.setCap(device.getCap());
        deviceById.setPower(device.getPower());
        deviceById.setIsPredicted(device.getIsPredicted());
        deviceById.setConversionRate(device.getConversionRate());
        deviceById.setWorkTime(times[0]+"-"+times[1]);
        /**********/
        //根据pointId找到对应的devCode 前端只传pointId，devCode需要后端从数据库中查
        if(device.getDevPointId()!=null) {
            Point devPoint = pointService.getPointById(device.getDevPointId());
            device.setDevCode(devPoint != null ? devPoint.getDevCode() : "点位不存在");
        }
//        else device.setDevCode("无对应点位");
        if(device.getBatteryPointId()!=null) {
            Point BatteryPoint = pointService.getPointById(device.getBatteryPointId());
            device.setBatteryCode(BatteryPoint != null ? BatteryPoint.getDevCode() : "点位不存在");
        }
//        else device.setBatteryCode("无对应点位");
        if(device.getTemperaturePointId()!=null) {
            Point TemperaturePoint = pointService.getPointById(device.getTemperaturePointId());
            device.setTemperatureCode(TemperaturePoint != null ? TemperaturePoint.getDevCode() : "点位不存在");
        }
//        else device.setTemperatureCode("无对应点位");

        deviceById.setDevCode(device.getDevCode()!=null?device.getDevCode():deviceById.getDevCode());
        deviceById.setDevPointId(device.getDevPointId()!=null?device.getDevPointId():deviceById.getDevPointId());

        deviceById.setBatteryCode(device.getBatteryCode()!=null?device.getBatteryCode():deviceById.getBatteryCode());
        deviceById.setBatteryPointId(device.getBatteryPointId()!=null?device.getBatteryPointId():deviceById.getBatteryPointId());

        deviceById.setTemperatureCode(device.getTemperatureCode()!=null?device.getTemperatureCode():deviceById.getTemperatureCode());
        deviceById.setTemperaturePointId(device.getTemperaturePointId()!=null?device.getTemperaturePointId():deviceById.getTemperaturePointId());
        /**********/
        deviceById.setPowerMonitorSwitch(device.getPowerMonitorSwitch()!=null?device.getPowerMonitorSwitch():deviceById.getPowerMonitorSwitch());
        deviceById.setIntervalTime(device.getIntervalTime()!=null?device.getIntervalTime():deviceById.getIntervalTime());
        deviceById.setAutoAdjustLastTime(device.getAutoAdjustLastTime()!=null?device.getAutoAdjustLastTime():deviceById.getAutoAdjustLastTime());
        deviceById.setDeviceMonitorSwitch(device.getDeviceMonitorSwitch()!=null?device.getDeviceMonitorSwitch():deviceById.getDeviceMonitorSwitch());

        deviceById.setEnableFactors(device.getEnableFactors()!=null?device.getEnableFactors():deviceById.getEnableFactors());

        deviceById.setStartButton(device.getStartButton()!=null?device.getStartButton():deviceById.getStartButton());
        deviceById.setStartCondition(device.getStartCondition()!=null?device.getStartCondition():deviceById.getStartCondition());
        deviceById.setStartOperator(device.getStartOperator()!=null?device.getStartOperator():deviceById.getStartOperator());
        deviceById.setStartValue(device.getStartValue()!=null?device.getStartValue():deviceById.getStartValue());

        deviceById.setEndButton(device.getEndButton()!=null?device.getEndButton():deviceById.getEndButton());
        deviceById.setEndCondition(device.getEndCondition()!=null?device.getEndCondition():deviceById.getEndCondition());
        deviceById.setEndOperator(device.getEndOperator()!=null?device.getEndOperator():deviceById.getEndOperator());
        deviceById.setEndValue(device.getEndValue()!=null?device.getEndValue():deviceById.getEndValue());

        if(deviceById.getDeviceType().getTypeId()==2){  //如果是储能设备
            deviceById.setUpperTemp(device.getUpperTemp());
            deviceById.setLowerTemp(device.getLowerTemp());
            deviceById.setColdorheat(device.getColdorheat());
            deviceById.setEndFlagId(device.getEndFlagId()!=null?device.getEndFlagId():deviceById.getEndFlagId());
        }

        List<AdditionalProperties> propertyList = new ArrayList<>();
        if(propertyId==null){
            if (propertyName!=null) {
                for (int i = 0; i < propertyName.length; i++) {
                    AdditionalProperties property = new AdditionalProperties(propertyName[i], propertyValue[i]);
                    property.setDevice(deviceById);
                    propertyList.add(property);
                }
            }
        }else {
            for (int i =0 ; i< propertyId.length;i++){
                AdditionalProperties property = new AdditionalProperties(propertyName[i],propertyValue[i]);
                property.setPropertyId(Integer.parseInt(propertyId[i]));
                property.setDevice(deviceById);
                propertyList.add(property);
            }
            for(int j  = propertyId.length;j<propertyName.length;j++){
                AdditionalProperties property = new AdditionalProperties(propertyName[j],propertyValue[j]);
                property.setDevice(deviceById);
                propertyList.add(property);
            }
        }
        deviceById.setPropertyList(propertyList);
        if (pic!=null&&pic.length!=0){
            for (int i = 0 ;i<pic.length;i++){
                if (!"".equals(pic[i].getOriginalFilename())) {
                    String fileName = UUID.randomUUID().toString() + pic[i].getOriginalFilename().substring(pic[i].getOriginalFilename().lastIndexOf("."));
                    pic[i].transferTo(new File(base + fileName));
                    if (i == 0) {
                        deviceById.setPicPath("/multipower/images/" + fileName);
                    } else {
                        deviceById.setHighlightPicPath("/multipower/images/" + fileName);
                    }
                }
            }
        }
//        System.out.println("更新："+deviceById.toString());
        deviceService.saveAndUpdateProperties(deviceById);
        map.put("message","update success");
        return map;
    }


    /**
     * 根据设备类型筛选设备，返回设备列表页面
     * @param typeId
     * @param model
     * @return
     */
    @GetMapping("/{type_id}")
    private String getAllDevicesByTypeId(@PathVariable("type_id") Integer typeId, Model model){
        List<Device> deviceList = deviceService.findDeviceByTypeId(typeId);
        List<DeviceInfoDTO> deviceInfoDTOS=new ArrayList<>();
        for (Device device:deviceList) {
            DeviceInfoDTO deviceInfoDTO=new DeviceInfoDTO();
            BeanUtils.copyProperties(device,deviceInfoDTO);

            if(device.getDevPointId()!=null) {
                Point devPoint = pointService.getPointById(device.getDevPointId());
                deviceInfoDTO.setDevName(devPoint != null ? devPoint.getPointName() : "点位不存在");
            }else deviceInfoDTO.setDevName("无对应点位");
            if(device.getBatteryPointId()!=null) {
                Point BatteryPoint = pointService.getPointById(device.getBatteryPointId());
                deviceInfoDTO.setBatteryName(BatteryPoint != null ? BatteryPoint.getPointName() : "点位不存在");
            }else deviceInfoDTO.setBatteryName("无对应点位");
            if(device.getTemperaturePointId()!=null) {
                Point TemperaturePoint = pointService.getPointById(device.getTemperaturePointId());
                deviceInfoDTO.setTemperatureName(TemperaturePoint != null ? TemperaturePoint.getPointName() : "点位不存在");
            }else deviceInfoDTO.setTemperatureName("无对应点位");

            deviceInfoDTOS.add(deviceInfoDTO);
        }
        model.addAttribute("deviceInfoDTOS",deviceInfoDTOS);
        return "device";
    }

    /**
     * 校验设备名字是否重复
     * @param deviceName
     * @return
     */
    @GetMapping("/check")
    @ResponseBody
    private Map checkDuplicateName(@RequestParam("deviceName")String deviceName){
        Map map = new HashMap();
        StringBuilder sb = new StringBuilder();
        boolean b = deviceService.checkDeviceName(deviceName);
        if (b) sb.append("yes");
        else sb.append("no");
        map.put("check",sb.toString());
        return map;
    }

    /**
     * 获取设备的高亮图片
     * @param deviceId
     * @return
     */
    @GetMapping("/getHighlightPic/{deviceId}")
    @ResponseBody
    public Map getHighlightPic(@PathVariable("deviceId")Integer deviceId){
        Device device = deviceService.findDeviceById(deviceId);
        Map map = new HashMap();
        if(device == null){
            map.put("msg","fail");
        }else {
            map.put("highlight",device.getHighlightPicPath());
        }
        return map;
    }

    /**
     * 图谱拖拽界面，更新设备在图谱上的坐标
     * @param xmlString
     * @return
     */
    @PostMapping("/updateDeviceCoordinates")
    @ResponseBody
    public Map updateDeviceCoordinates(@RequestParam("xmlString")String xmlString,
                                       @RequestParam(defaultValue = "0",value = "graphId") Integer graphId){
        if(graphId != 0){
            List<GraphDev> graphDevs = ReadXml.readStringXml(xmlString);
            if(graphDevs != null){
                for (GraphDev g:graphDevs){
                    g.setGraphId(graphId);
                    GraphDev gg = graphDevService.findGraphDevsByDeviceIdAndGraphId(g);
                    g.setVersion(gg.getVersion());
                }

                graphDevService.updateDeviceCoordinates(graphDevs);
            }
        }
        Map map = new HashMap();
        map.put("message","success");
        return map;
    }

    @RequestMapping(value = "getall")
    @ResponseBody
    public Result<List<DeviceDTO>> getDeviceByGraphId(@RequestParam("graphId") Integer graphId) {
        try {
            List<DeviceDTO> devices = deviceService.getDevicesByGraphId(graphId);
            return Result.ok(devices);
        } catch (Exception ex) {
            return Result.error(String.format("获取设备信息失败 [%s]", ex.getMessage()));
        }
    }

}
